#include "Interface.hpp"

namespace mi
{
  /*static*/ Interface& Interface::I()
  {
    if (instance == NULL)
      instance = new Interface();
    return (*instance);
  }

  bool Interface::AddWidget(Widget* additionalWidget)
  {
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      if (widgets[i]->GetInternalID().compare(additionalWidget->GetInternalID()) == 0)
        return false;
    }
    widgets.push_back(additionalWidget);
    return true;
  }

  bool Interface::MouseClick(sf::Mouse::Button button, sf::MouseState state, int x, int y)
  {
    Widget* tmp = NULL;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      tmp = widgets[i]->MouseClick(button, state, x, y);
      if (tmp != NULL)
      {
        activeWidget = tmp;
        // find the top-level owner of this widget, and move that owner to front
        MoveToTopOfWidgets(FindTopLevelOwner(tmp));
        return true;  // consumed event
      }
    }
    activeWidget = NULL;
    return false; // no consumption
  }
  
  bool Interface::MouseMoved(int x, int y, int dx, int dy)
  {
    Widget* tmp = NULL;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      if (tmp == NULL)
      {
        tmp = widgets[i]->MouseMoved(x,y,dx,dy);
      }
      else
        widgets[i]->MouseMoved(-1,-1,dx,dy);
    }
    if (tmp != NULL)
    {
      return true;
    }
    return false;
  }
  
  bool Interface::MouseDragged(int x, int y, int dx, int dy)
  {
    if (activeWidget != NULL)
    {
      activeWidget->MouseDragged(x,y,dx,dy);
      return true;
    }
    return false;
  }
  
  bool Interface::MouseWheel(int dir)
  {
    Widget *tmp;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      tmp = widgets[i]->MouseWheel(dir);
      if (tmp != NULL)
        return true;
    }
    return false;
  }
  
  bool Interface::KeysDown(sf::Event::KeyEvent key)
  {
    Widget *tmp;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      tmp = widgets[i]->KeysDown(key);
      if (tmp != NULL)
        return true;
    }
    return false;
  }
  
  bool Interface::KeysUp(sf::Event::KeyEvent key)
  {
    Widget *tmp;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      tmp = widgets[i]->KeysUp(key);
      if (tmp != NULL)
        return true;
    }
    return false;
  }

  bool Interface::TextEntered(char ch)
  {
    Widget *tmp;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      tmp = widgets[i]->TextEntered(ch);
      if (tmp != NULL)
        return true;
    }
    return false;
  }

  void Interface::OnResize(int w, int h)
  {
    if (w == 0 || h == 0)
        return;
    Widget::OnResize(w, h);
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      widgets[i]->SetPos(widgets[i]->GetPos());
    }
  }

  void Interface::Draw2D()
  {
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,0,App::I().Size().x, App::I().Size().y);
    for (int i = (int)(widgets.size()-1); i >= 0; i--)
    {
      widgets[i]->Draw2D();
    }
    glDisable(GL_SCISSOR_TEST);
  }

  bool Interface::Update(double dTime)
  {
    bool result;
    for (unsigned int i = 0; i < widgets.size(); i++)
    {
      result = widgets[i]->Update(dTime);
      if (result)
        return result;
    }
    return false;
  }

// private

  Interface::Interface()
  {
    activeWidget = NULL;
    mouseOverWidget = NULL;
  }

  Interface::Interface(Interface& other)
  {
    // do nothing
  }

  void Interface::operator = (Interface& other)
  {
    // do nothing
  }

  bool Interface::MoveToTopOfWidgets(Widget* ptr)
  {
    std::deque<Widget*>::iterator it = widgets.begin();
    unsigned int i = 0;
    while (it != widgets.end())
    {
      if (widgets[i]->GetInternalID().compare(ptr->GetInternalID()) == 0)
      {
        Widget* tmp = widgets[i];
        widgets.erase(it);
        widgets.push_front(tmp);
        return true;    // Successfully moved element
      }
      i++;
      it++;
    }
    return false;   // could not move, because it wasn't in deque
  }

  Widget* Interface::FindTopLevelOwner(Widget* ofThisWidget)
  {
    for (unsigned int j = 0; j < widgets.size(); j++)
    {
      if (widgets[j]->Contains(ofThisWidget))
        return widgets[j];
    }
    // This should never happen
    return NULL;
  }

  /*static*/ Interface * Interface::instance = NULL;
}